<template>
  <!-- 航线绘制：点击加点，点用canvas渲染，折线连接；可编辑点高度，保存至 store -->
  <div class="page-wrap">
    <div class="toolbar">
      <el-input
        v-model="routeName"
        size="small"
        placeholder="航线名称"
        style="width: 200px; margin-right: 8px"
      />
      <el-button size="small" type="success" @click="saveRoute">保存</el-button>
      <el-button size="small" type="warning" @click="clearAll">清空</el-button>
    </div>

    <CesiumViewer
      ref="viewerComp"
      :options="viewerOptions"
      :camera="camera"
      :homeZoomOutFactor="0.4"
    >
      <template #entities></template>
    </CesiumViewer>

    <!-- 高度编辑弹窗 -->
    <el-dialog v-model="heightDialog.visible" title="设置点高度" width="300px">
      <el-input-number
        v-model="heightDialog.height"
        :min="0"
        :max="20000"
        :step="10"
      />
      米
      <template #footer>
        <el-button @click="heightDialog.visible = false">取消</el-button>
        <el-button type="primary" @click="applyHeight">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, onBeforeUnmount } from "vue";
import * as Cesium from "cesium";
import CesiumViewer from "@/components/cesium/CesiumViewer.vue";
import { useAirRoutesStore } from "@/stores/airroutes";
import { ElMessage } from "element-plus";

const store = useAirRoutesStore();

const viewerComp = ref(null);
const viewer = ref(null);
let handler = null; // 事件处理器

const routeName = ref(""); // 航线名称
// 模式简化：不再提供按钮切换，默认左键添加节点；编辑高度通过点击已有点自动弹窗

// 逻辑点（经纬高）
const points = ref([]); // [{lon,lat,height}]

// 用于 CanvasOverlay
let overlay = null; // HTMLCanvasElement
let ctx = null; // CanvasRenderingContext2D
let dpr = 1; // 简化为 1:1（使用 CSS 像素坐标绘制）
let postRenderRemove = null; // 移除 postRender 的函数

// 折线实体与垂直虚线实体集合
let lineEntity = null;
let verticalEntities = [];

const viewerOptions = {
  animation: false,
  baseLayerPicker: false,
  geocoder: false,
  timeline: false,
  fullscreenButton: true,
  sceneModePicker: true,
};
const camera = {
  lon: 104.195397,
  lat: 35.86166,
  height: 8000000,
  heading: 0,
  pitch: -45,
  roll: 0,
};

onMounted(() => {
  nextTick(() => {
    if (viewerComp.value && typeof viewerComp.value.getViewer === "function")
      viewer.value = viewerComp.value.getViewer();
    const v = viewer.value;
    if (!v) return;
    // 事件
    handler = new Cesium.ScreenSpaceEventHandler(v.scene.canvas);
    handler.setInputAction(onLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // 移动：用于预览线/面
    // 注：本页无需右键完成操作，避免无意义回调导致报错
    handler.setInputAction(onMouseMove, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    // 移除右键绑定（原先用于结束图形）
    // handler.setInputAction(finishShape, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    // 创建 Canvas 覆盖层
    createCanvasOverlay(v);
    // 首次渲染
    redrawCanvas();
  });
});

onBeforeUnmount(() => {
  if (handler) handler.destroy();
  if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
  if (postRenderRemove) postRenderRemove();
});

function createCanvasOverlay(v) {
  overlay = document.createElement("canvas");
  overlay.style.position = "absolute";
  overlay.style.left = 0;
  overlay.style.top = 0;
  overlay.style.pointerEvents = "none";
  overlay.style.zIndex = 999; // 确保在 Cesium 画布之上
  // 处理高清屏：按照 DPR 缩放
  dpr = window.devicePixelRatio || 1;
  function resizeCanvas() {
    const w = v.canvas.clientWidth;
    const h = v.canvas.clientHeight;
    // 使用样式尺寸覆盖到容器大小，避免影响容器布局
    overlay.style.width = w + "px";
    overlay.style.height = h + "px";
    // 实际像素尺寸与 CSS 像素一致，避免坐标系不一致导致偏移
    overlay.width = Math.max(1, Math.floor(w));
    overlay.height = Math.max(1, Math.floor(h));
    ctx = overlay.getContext("2d");
    // 不再进行 DPR 缩放，直接用 CSS 像素坐标绘制
  }
  v.container.appendChild(overlay);
  const ro = new ResizeObserver(resizeCanvas);
  ro.observe(v.container);
  resizeCanvas();
  // 每帧渲染后重绘一次，保证与相机视图同步且避免抖动
  const postRender = () => {
    redrawCanvas();
  };
  v.scene.postRender.addEventListener(postRender);
  postRenderRemove = () => {
    try {
      v.scene.postRender.removeEventListener(postRender);
    } catch (_) {}
  };
  // 初始化一次实体同步
  syncPolyline();
}

function worldToScreen(v, lon, lat, height) {
  const cart = Cesium.Cartesian3.fromDegrees(lon, lat, height || 0);
  // 优先使用更通用的 API：scene.cartesianToCanvasCoordinates
  if (typeof v.scene.cartesianToCanvasCoordinates === "function") {
    return v.scene.cartesianToCanvasCoordinates(cart);
  }
  // 兼容旧接口
  if (
    Cesium.SceneTransforms &&
    typeof Cesium.SceneTransforms.wgs84ToWindowCoordinates === "function"
  ) {
    return Cesium.SceneTransforms.wgs84ToWindowCoordinates(v.scene, cart);
  }
  return null;
}

function onLeftClick(movement) {
  const v = viewer.value;
  if (!v) return;
  // 先判断是否点击到了已有的屏幕点（用于高度编辑）
  const hit = pickNearestScreenPoint(movement.position);
  if (hit) {
    heightDialog.value.index = hit.index;
    heightDialog.value.height = points.value[hit.index].height || 0;
    heightDialog.value.visible = true;
    return;
  }
  // 否则尝试在地图上添加新点
  const cartesian = v.camera.pickEllipsoid(
    movement.position,
    v.scene.globe.ellipsoid
  );
  if (!cartesian) return;
  const c = Cesium.Cartographic.fromCartesian(cartesian);
  const p = {
    lon: Cesium.Math.toDegrees(c.longitude),
    lat: Cesium.Math.toDegrees(c.latitude),
    height: 180,
  };
  points.value.push(p);
  syncPolyline();
  redrawCanvas();
}

function pickNearestScreenPoint(mouse) {
  const v = viewer.value;
  if (!v) return null;
  if (!points.value.length) return null;
  let best = null;
  let bestDist = 1e9;
  points.value.forEach((pt, i) => {
    const win = worldToScreen(v, pt.lon, pt.lat, pt.height);
    if (!win) return;
    const dx = win.x - mouse.x;
    const dy = win.y - mouse.y;
    const d = Math.hypot(dx, dy);
    if (d < bestDist && d <= 20) {
      bestDist = d;
      best = { index: i, win };
    }
  });
  return best;
}

const heightDialog = ref({ visible: false, index: -1, height: 0 });
function applyHeight() {
  const i = heightDialog.value.index;
  if (i < 0) return;
  points.value[i].height = Number(heightDialog.value.height || 0);
  heightDialog.value.visible = false;
  syncPolyline(); // 更新垂直虚线与主线
  redrawCanvas();
  try {
    const v = viewer.value;
    v && v.requestRender && v.requestRender();
  } catch (_) {}
}

function syncPolyline() {
  const v = viewer.value;
  if (!v) return;
  // 仅维护垂直虚线；主连接线用 Canvas 绘制，避免与实体折线重复
  if (lineEntity) {
    try {
      v.entities.remove(lineEntity);
    } catch (_) {}
    lineEntity = null;
  }
  // 先清空旧的垂直虚线
  verticalEntities.forEach((e) => v.entities.remove(e));
  verticalEntities = [];
  // 逐点生成垂直虚线
  points.value.forEach((p) => {
    const base = Cesium.Cartesian3.fromDegrees(p.lon, p.lat, 0);
    const h = Number(p.height || 0);
    const topHeight = h > 0 ? h : 500; // 若高度为0，则显示一个 500m 的辅助虚线，便于可见
    const top = Cesium.Cartesian3.fromDegrees(p.lon, p.lat, topHeight);
    const e = v.entities.add({
      polyline: {
        positions: [base, top],
        width: 2,
        clampToGround: false,
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.fromCssColorString("#00e5ff"),
          dashLength: 16,
          dashPattern: 255,
        }),
      },
      show: true,
    });
    verticalEntities.push(e);
  });
  try {
    v.requestRender && v.requestRender();
  } catch (_) {}
}

function redrawCanvas() {
  if (!ctx || !viewer.value) return;
  const v = viewer.value;
  // 清空整张画布（按 CSS 像素尺寸）
  const w = overlay.width;
  const h = overlay.height;
  ctx.clearRect(0, 0, w, h);
  // 画连接线（屏幕空间）
  if (points.value.length >= 2) {
    ctx.beginPath();
    points.value.forEach((pt, idx) => {
      const win = worldToScreen(v, pt.lon, pt.lat, pt.height);
      if (!win) return;
      if (idx === 0) ctx.moveTo(win.x, win.y);
      else ctx.lineTo(win.x, win.y);
    });
    ctx.lineWidth = 4;
    ctx.strokeStyle = "#FFD200"; // 明亮黄色
    ctx.lineJoin = "round";
    ctx.lineCap = "round";
    ctx.stroke();
  }
  // 画节点（蓝底圆 + 序号文字）
  points.value.forEach((pt, idx) => {
    const win = worldToScreen(v, pt.lon, pt.lat, pt.height);
    if (!win) return;
    // 圆底
    ctx.beginPath();
    ctx.arc(win.x, win.y, 10, 0, Math.PI * 2);
    ctx.fillStyle = "#1677ff"; // 蓝色背景
    ctx.fill();
    // 白色描边增强对比
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#ffffff";
    ctx.stroke();
    // 序号
    ctx.fillStyle = "#ffffff";
    ctx.font = "12px sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(String(idx + 1), win.x, win.y);
  });
}

function clearAll() {
  points.value = [];
  const v = viewer.value;
  if (v) {
    if (lineEntity) {
      v.entities.remove(lineEntity);
      lineEntity = null;
    }
    verticalEntities.forEach((e) => v.entities.remove(e));
    verticalEntities = [];
  }
  redrawCanvas();
}

function saveRoute() {
  if (!routeName.value) {
    ElMessage.warning("请输入航线名称");
    return;
  }
  if (points.value.length < 2) {
    ElMessage.warning("至少需要两个点");
    return;
  }
  const route = {
    id: `${Date.now()}`,
    name: routeName.value,
    points: points.value.map((p) => ({ ...p })),
    createdAt: new Date().toISOString(),
  };
  store.saveRoute(route);
  ElMessage.success("已保存至航线库");
}

function onMouseMove(movement) {
  // 鼠标移动时仅重绘，以便在相机变化或容器尺寸变化后保持画布与场景同步
  redrawCanvas();
}
</script>

<style scoped>
.page-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.toolbar {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 20;
  background: rgba(255, 255, 255, 0.9);
  padding: 6px 8px;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
</style>
